package de.tud.binpacking.ui;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import de.tud.binpacking.Benchmark;
import de.tud.binpacking.data.Solution;
import de.tud.binpacking.events.BestSolutionListener;
import de.tud.binpacking.instance.Importer;

public class BinPackingUi {

	private static Text instPathText;
	private static Text resultsPathText;

	private Combo nOrdersCombo;
	private Combo capacityCombo;
	private Text progressText;
	private Table table;
	private Text nameText;
	private Menu menu;

	/**
	 * @wbp.parser.constructor
	 */	
	public BinPackingUi() {
		open();
	}

	public BinPackingUi(int nOrders, int capacity, int maxRuntime, String instPath, String resultsPath) {

	}

	public void open() {

		Display display = Display.getDefault();
		final Shell shell = new Shell(display);
		shell.setSize(831, 617);
		shell.setLayout(new GridLayout(2, false));

		Group grpInput = new Group(shell, SWT.NONE);
		grpInput.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
		grpInput.setLayout(new GridLayout(6, false));
		grpInput.setText("Input");

		Label lblName = new Label(grpInput, SWT.NONE);
		lblName.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblName.setText("Name");

		nameText = new Text(grpInput, SWT.BORDER);
		nameText.setText("Benchmark");
		nameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 5, 1));

		Label lblInstance = new Label(grpInput, SWT.NONE);
		lblInstance.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblInstance.setText("Instance");

		instPathText = new Text(grpInput, SWT.BORDER);
		instPathText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 4, 1));

		Button browseInstancePathButton = new Button(grpInput, SWT.NONE);
		browseInstancePathButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		browseInstancePathButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				DirectoryDialog dialog = new DirectoryDialog(shell);

				instPathText.setText(dialog.open());
			}
		});
		browseInstancePathButton.setText("Browse...");

		Label lblOutput = new Label(grpInput, SWT.NONE);
		lblOutput.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblOutput.setText("Output");

		resultsPathText = new Text(grpInput, SWT.BORDER);
		resultsPathText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 4, 1));

		Button browseOutputPathButton = new Button(grpInput, SWT.NONE);
		browseOutputPathButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		browseOutputPathButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				DirectoryDialog dialog = new DirectoryDialog(shell);

				resultsPathText.setText(dialog.open());
			}
		});

		browseOutputPathButton.setText("Browse...");

		Label lblOrders = new Label(grpInput, SWT.NONE);
		lblOrders.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblOrders.setText("Orders");

		nOrdersCombo = new Combo(grpInput, SWT.READ_ONLY);
		nOrdersCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
		nOrdersCombo.setItems(new String[] {"30", "50", "70", "90"});
		nOrdersCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		nOrdersCombo.select(0);

		Label lblCapacity_1 = new Label(grpInput, SWT.NONE);
		lblCapacity_1.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblCapacity_1.setText("Capacity");

		capacityCombo = new Combo(grpInput, SWT.READ_ONLY);
		capacityCombo.setItems(new String[] {"30", "45", "60", "75"});
		capacityCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
		capacityCombo.select(0);

		Label label = new Label(grpInput, SWT.NONE);
		label.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
		new Label(grpInput, SWT.NONE);

		Group grpStatistics = new Group(shell, SWT.NONE);
		grpStatistics.setLayout(new GridLayout(1, false));
		grpStatistics.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
		grpStatistics.setText("Statistics");

		table = new Table(grpStatistics, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		table.setHeaderVisible(true);

		TableColumn tblclmnBenchmark = new TableColumn(table, SWT.NONE);
		tblclmnBenchmark.setWidth(300);
		tblclmnBenchmark.setText("Benchmark");

		TableColumn tblclmnOrders = new TableColumn(table, SWT.NONE);
		tblclmnOrders.setWidth(100);
		tblclmnOrders.setText("Orders");

		TableColumn tblclmnCapacity = new TableColumn(table, SWT.NONE);
		tblclmnCapacity.setWidth(100);
		tblclmnCapacity.setText("Capacity");

		TableColumn tblclmnBestSolution = new TableColumn(table, SWT.NONE);
		tblclmnBestSolution.setWidth(200);
		tblclmnBestSolution.setText("Best Solution");

		menu = new Menu(table);
		table.setMenu(menu);

		// Menu items

		MenuItem runItem = new MenuItem(menu, SWT.NONE);
		runItem.setText("Run");
		runItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				for (TableItem item : table.getSelection()) {
					Thread thread = new Thread((Benchmark) item.getData());
					thread.start();
				}
			}
		});

		MenuItem deleteItem = new MenuItem(menu, SWT.NONE);
		deleteItem.setText("Delete");
		deleteItem.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				for (TableItem item : table.getSelection()) {
					item.dispose();
				}
				table.update();
			}
		});

		Group grpControls = new Group(shell, SWT.NONE);
		grpControls.setLayout(new GridLayout(5, false));
		grpControls.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		grpControls.setText("Controls");

		Button btnRun = new Button(grpControls, SWT.NONE);
		btnRun.setText("Run");

		Button btnCancel = new Button(grpControls, SWT.NONE);
		btnCancel.setText("Cancel");

		Button btnLoad = new Button(grpControls, SWT.NONE);
		btnLoad.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				loadBenchmark();
			}
		});

		btnLoad.setText("Load");

		Label lblTimeout = new Label(grpControls, SWT.NONE);
		lblTimeout.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
		lblTimeout.setText("Timeout (min)");

		Spinner maxRuntimeSpinner = new Spinner(grpControls, SWT.BORDER);
		maxRuntimeSpinner.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));

		Group grpProgress = new Group(shell, SWT.NONE);
		grpProgress.setLayout(new GridLayout(1, false));
		grpProgress.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
		grpProgress.setText("Progress");

		progressText = new Text(grpProgress, SWT.BORDER | SWT.READ_ONLY);
		GridData gd_progressText = new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1);
		gd_progressText.widthHint = 206;
		progressText.setLayoutData(gd_progressText);
		maxRuntimeSpinner.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});

		shell.open();
		shell.setMaximized(true);

		while(!shell.isDisposed()) {
			display.readAndDispatch();
		}
	}

	public void loadBenchmark() {

		Integer orders = Integer.parseInt(nOrdersCombo.getText());
		Integer capacity = Integer.parseInt(capacityCombo.getText());
		String path = instPathText.getText();

		Benchmark benchmark;
		try {
			benchmark = new Benchmark(Importer.importInstances(orders, capacity, path));


			final TableItem item = new TableItem(table, SWT.NONE);
			item.setData(benchmark);
			item.setText(0, nameText.getText());
			item.setText(1, orders.toString());
			item.setText(2, capacity.toString());

			benchmark.addSolutionFoundListener(new BestSolutionListener() {

				@Override
				public void bestSolutionFound(final Solution solution) {
					item.getDisplay().syncExec(new Runnable() {

						@Override
						public void run() {
							item.setText(3, Double.toString(solution.getCosts()));
						}
					});
				}
			});

		} catch (Exception e) {
			MessageBox messageBox = new MessageBox(new Shell(), SWT.ERROR);
			messageBox.setMessage(e.getMessage());
			messageBox.open();
			e.printStackTrace();
		}

		table.update();
	}

	public void setMessage(final String message) {
		progressText.getDisplay().syncExec(new Runnable() {

			@Override
			public void run() {
				progressText.setText(message);
			}
		});
	}
}
